package com.shun.common.log.aspect;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.shun.base.dto.SysOperLogDto;
import com.shun.common.log.annotation.ShunLog;
import com.shun.common.log.event.ShunLogEvent;
import com.shun.common.utils.ServletUtils;
import com.shun.common.utils.SpringContextUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * 操作日志记录处理AOP
 * 
 * @author lushaonan
 * @date 2020-04-13
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

	@Around("@annotation(slog)")
	@SneakyThrows
	public Object doLogs(ProceedingJoinPoint point, ShunLog slog) {
		log.debug("日志参数:{}", slog);
		Object result = point.proceed();
		saveLog(point, slog, result);
		return result;
	}

	/**
	 * 保存日志
	 * 
	 * @param point
	 * @param slog
	 */
	public void saveLog(ProceedingJoinPoint point, ShunLog slog, Object result) {
		// 获得方法名称
		String methodName = point.getSignature().getName();
		// 创建系统执行日志
		SysOperLogDto operLog = new SysOperLogDto();
		HttpServletRequest request  = ServletUtils.getRequest();
		String userAgent = request.getHeader("User-Agent");
		String os = UserAgentUtil.parse(userAgent).getOs().getName();
		String clientIp = ServletUtil.getClientIP(ServletUtils.getRequest());
		operLog.setBusinessType(slog.logType().ordinal());
		operLog.setOperTitle(slog.title());
		operLog.setOperMethod(methodName);
		operLog.setRequestMethod(request.getMethod());
		operLog.setOperUserId(StpUtil.getLoginIdAsString());
		operLog.setOperUrl(request.getRequestURI().toString());
		operLog.setOperIp(clientIp);
		operLog.setOperTime(LocalDateTime.now());
		if (slog.isSaveRequestData()) {
			operLog.setOperParam(getArgs(point.getArgs()));
		}
		if (ObjectUtil.isNotNull(result)) {
			operLog.setJsonResult(JSONUtil.toJsonStr(result));
		} else {
			operLog.setStatus("1");// 操作失败
			operLog.setErrorMsg("操作失败");
		}
		log.debug("操作日志：{}",operLog);
		SpringContextUtil.publishEvent(new ShunLogEvent(operLog));
	}

	/**
	 * 获得参数处理
	 * 
	 * @param args
	 * @return
	 */
	public String getArgs(Object[] args) {
		StringBuilder result = new StringBuilder("");
		for (Object obj : args) {
			result.append(obj.toString());
		}
		JSONObject jsonObject = new JSONObject();
		jsonObject.append("param",result.toString());
		return jsonObject.toString();
	}
}
